package affd.logic;

import java.util.ArrayList;

public class DateAnonymizer implements Anonymizer {

	public static final String MODIFICATION_CLASS = "date";
	
	private static String DAY = "DD";
	private static String MONTH = "MM";
	private static String YEAR = "YYYY";

	/**
	 * 
	 */
	public DateAnonymizer() {
	}

	@Override
	public void process(ArrayList<Sentence> sentences) throws LogicException {
		for(Sentence sentence : sentences) {
			ArrayList<Token> tokens = sentence.getTokens();
			for(Token token : tokens) {
				if(isDate(token)) {
					anonymize(token);
				}
			}
		}	
	}

	@Override
	public void anonymize(Token token) {
		String[] parts = token.getContent().trim().split("\\.");
		
		if (parts.length >= 3) { // The date consist of three parts separated with '.': day.month.year
			parts[0] = DAY;
			parts[1] = MONTH;
			parts[2] = YEAR;
			
			String newContent = "";
		
			for (int i = 0; i < parts.length; i++) {
				if (i != 0) {
					newContent += ".";
				}
				newContent += parts[i];
			}
			if (token.getContent().lastIndexOf(".") == token.getContent().length() - 1) {
				newContent += ".";
			}
			
			token.modifyContent(newContent, MODIFICATION_CLASS, null);
		}		
	}
	
	/**
	 * Checks if the given token is a date. This method currently replaces only
	 * dates which are in the form day.month.year
	 * 
	 * @param token The token which is checked for a date
	 * @return Boolean value which tells whether the token contained a date or not
	 */
	private boolean isDate(Token token) {
		String[] parts = token.getContent().trim().split("\\.");
		
		if (parts.length >= 3) { // The date consist of three parts separated with '.': day.month.year
			for (int i = 0; i < 3; i++) {
				try {
					int part = Integer.parseInt(parts[i]); // Each part of the date should be parsed to integer
					if (i == 2 && isValid(part, i)) {
						return true;
					} else if (!isValid(part, i)) {
						return false;
					}
				} catch (NumberFormatException e) {
					break;
				}
			}
		}
		return false;
	}

	/**
	 * Checks if the given part could be a part of a date.
	 * 
	 * @param partOfDate The part which is checked if it represents a day, a month or a year
	 * @param i The value which indicates if the value is checked for a being day, a month or a year
	 * @return isValidPartOfDate Boolean value which tells if the given integer could be part of a real date
	 */
	private boolean isValid(int partOfDate, int i) {
		if (i == 0) {
			if (partOfDate > 0 && partOfDate <= 31) {
				return true;
			}
		} else if (i == 1) {
			if (partOfDate > 0 && partOfDate <= 12) {
				return true;
			}
		} else if (i == 2) {
			if (partOfDate > 0) { // No negative years
				return true;
			}
		}
		return false;
	}
}
